package com.youlai.threadpool.reject;


import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 示例类展示了自定义 ThreadPoolExecutor 的 CallerRunsPolicy 策略，
 * 并在拒绝任务时打印日志。
 * <p>
 * 创建人: Ray
 * 创建时间: 2024/9/5
 */
@Slf4j
public class CallerRunsPolicyTest {

    public static void main(String[] args) {
        Executor executor = createExecutor();

        // 提交一些任务给线程池
        for (int i = 1; i <= 10; i++) {
            final int taskNumber = i;
            executor.execute(() -> {
                log.info("Task {} is running in thread: {}", taskNumber, Thread.currentThread().getName());
                try {
                    // 模拟任务执行时间
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    log.error("Task {} was interrupted", taskNumber, e);
                }
            });
        }
    }

    /**
     * 创建一个 ThreadPoolExecutor，使用自定义的 CallerRunsPolicy 策略。
     *
     * @return ThreadPoolExecutor 实例
     */
    public static Executor createExecutor() {
        // 创建一个容量为2的阻塞队列
        ArrayBlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(2);

        // 创建一个线程池，核心线程数为2，最大线程数为2，保持时间为0秒
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                2, // 核心线程数
                2, // 最大线程数
                0L, // 线程闲置时间
                TimeUnit.MILLISECONDS, // 时间单位
                workQueue, // 阻塞队列
                // new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
                new CustomCallerRunsPolicy() // 自定义的饱和策略
        );

        return executor;
    }

    /**
     * 自定义的 CallerRunsPolicy 策略，继承自 ThreadPoolExecutor.CallerRunsPolicy，
     * 并在拒绝任务时打印日志信息。
     */
    static class CustomCallerRunsPolicy extends ThreadPoolExecutor.CallerRunsPolicy {
        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            // 打印日志信息
            log.warn("Task {} rejected from {}", r.toString(), e.toString());

            // 调用父类的方法，在调用者线程中执行任务
            super.rejectedExecution(r, e);
        }
    }
}
